package cn.gok.testclass;

import java.lang.reflect.Method;

/**
 * @Author: chenfan
 * @Description:  通过Class实例对 相应类的 方法的操作
 */
public class Demo03 {
    public static void main(String[] args) throws Exception {
        Class<?> aClass = Class.forName("cn.gok.entity.Person");
        Object obj = aClass.getConstructor().newInstance();

        /*
         * 1、在反射机制中，所有的方法 都是一个Method对象
         *
         *  getMethods();  获取所有的public方法，包含父类中的方法，以Method[] 对象的形式返回
         *  getMethod(String methodName, Class<?>[] paramTypes); 获取指定的方法
         *      methodName ：方法名
         *      paramTypes ： 方法中的形参类型
         *
         *  getDeclaredMethods(); 获取包括private在内的所有方法 ，但是仅限于本类中的方法
         *  getDeclaredMethods(String methodName, Class<?>[] paramTypes) 获取包括private在内的 指定方法
         *
         */
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }
        System.out.println("================================================");


        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod.getName());
        }
        System.out.println("================================================");


        /*
            2、方法的调用
                   invoke(Object obj, Object... args)

                        obj: 表示具体的对象（调用哪个对象的方法）
                        args：方法所需要的参数

                注：不管是void还是非void，都是调用invoke方法

                    invoke方法会返回一个Object，表示此方法执行返回值
                    如果是void方法，我们不接收其返回值即可
         */
        Method getAge = aClass.getMethod("getAge", null);
        Object age = getAge.invoke(obj, null);
        System.out.println(age);


        Method setAge = aClass.getMethod("setAge", int.class);
        setAge.invoke(obj, 30);

        age = getAge.invoke(obj, null);
        System.out.println(age);


        System.out.println("================================================");
        /*
            3、打破私有封装
                    和属性一样，私有方法是不可以直接调用的，否则会抛出异常
         */

        Method test = aClass.getDeclaredMethod("test", null);
        test.setAccessible(true);
        test.invoke(obj, null);


    }
}
